//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#include <buola/image.h>

#include <buola/xml.h>
#include <buola/image/cfontinfo.h>

#include <boost/functional/hash.hpp>

namespace buola { namespace img {

CFontInfo::CFontInfo()
{
    mValid=VALID_NONE;
}

CFontInfo::CFontInfo(const CFontInfo &pOther)
{
    mValid=VALID_NONE;
    (*this)=pOther;
}

CFontInfo::CFontInfo(const std::string &pFamily,double pSize)
{
    mValid=VALID_NONE;
    SetFamily(pFamily);
    SetSize(pSize);
}

CFontInfo::CFontInfo(const std::string &pFamily,double pSize,
                        const std::string &pStyle)
{
    mValid=VALID_NONE;
    SetFamily(pFamily);
    SetSize(pSize);
    SetStyle(pStyle);
}

CFontInfo::CFontInfo(const std::string &pFamily,double pSize,
                        EFontWeight pWeight,EFontSlant pSlant)
{
    mValid=VALID_NONE;
    SetFamily(pFamily);
    SetSize(pSize);
    SetWeight(pWeight);
    SetSlant(pSlant);
}

CFontInfo::CFontInfo(xml::CNode pNode)
{
    mValid=VALID_NONE;
    SetFamily(pNode.GetStringAttrib("family"));

    int lSize;
    if((lSize=pNode.GetIntAttrib("size")))
    {
        SetSize(lSize);
    }
    int lAngle;
    if((lAngle=pNode.GetIntAttrib("angle")))
    {
        SetAngle(lAngle);
    }
    if(pNode.GetBoolAttrib("mono"))
    {
        //TODO
    }
    if(pNode.GetBoolAttrib("noantialias"))
    {
        SetAntialias(false);
    }
    if(pNode.GetBoolAttrib("italic"))
    {
        SetSlant(EFontSlant::ITALIC);
    }
    if(pNode.GetBoolAttrib("bold"))
    {
        SetWeight(EFontWeight::BOLD);
    }
    if(pNode.GetBoolAttrib("under"))
    {
        //TODO
    }
    if(pNode.GetBoolAttrib("strike"))
    {
        //TODO
    }
}

CFontInfo::~CFontInfo()
{
}

void CFontInfo::SetFamily(const std::string &pFamily)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_FAMILY;
    mFamily=pFamily;
}

void CFontInfo::SetStyle(const std::string &pStyle)
{
    mValid&=~VALID_HASH;
    mValid&=~(VALID_WEIGHT|VALID_SLANT);
    mValid|=VALID_STYLE;
    mStyle=pStyle;
}

void CFontInfo::SetSlant(EFontSlant pSlant)
{
    mValid&=~VALID_HASH;
    mValid&=~VALID_STYLE;
    mValid|=VALID_SLANT;
    mSlant=pSlant;
}

void CFontInfo::SetWeight(EFontWeight pWeight)
{
    mValid&=~VALID_HASH;
    mValid&=~VALID_STYLE;
    mValid|=VALID_WEIGHT;
    mWeight=pWeight;
}

void CFontInfo::SetSize(double pSize)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_SIZE;
    mSize=pSize;
}

void CFontInfo::SetWidth(int pWidth)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_WIDTH;
    mWidth=pWidth;
}

void CFontInfo::SetAspect(double pAspect)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_ASPECT;
    mAspect=pAspect;
}

void CFontInfo::SetPixelSize(double pPixelSize)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_PIXELSIZE;
    mPixelSize=pPixelSize;
}

void CFontInfo::SetSpacing(int pSpacing)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_SPACING;
    mSpacing=pSpacing;
}

void CFontInfo::SetFoundry(const std::string &pFoundry)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_FOUNDRY;
    mFoundry=pFoundry;
}

void CFontInfo::SetAntialias(bool pAntialias)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_ANTIALIAS;
    mAntialias=pAntialias;
}

void CFontInfo::SetDPI(double pDPI)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_DPI;
    mDPI=pDPI;
}

void CFontInfo::SetAngle(double pAngle)
{
    mValid&=~VALID_HASH;
    mValid|=VALID_ANGLE;
    mAngle=pAngle;
}

bool CFontInfo::operator==(const CFontInfo &pRH) const
{
    if(mValid!=pRH.mValid) return false;

    if((mValid&VALID_FAMILY)&&mFamily!=pRH.mFamily) return false;
    if((mValid&VALID_STYLE)&&mStyle!=pRH.mStyle) return false;
    if((mValid&VALID_SLANT)&&mSlant!=pRH.mSlant) return false;
    if((mValid&VALID_WEIGHT)&&mWeight!=pRH.mWeight) return false;
    if((mValid&VALID_SIZE)&&mSize!=pRH.mSize) return false;
    if((mValid&VALID_WIDTH)&&mWidth!=pRH.mWidth) return false;
    if((mValid&VALID_ASPECT)&&mAspect!=pRH.mAspect) return false;
    if((mValid&VALID_PIXELSIZE)&&mPixelSize!=pRH.mPixelSize) return false;
    if((mValid&VALID_SPACING)&&mSpacing!=pRH.mSpacing) return false;
    if((mValid&VALID_FOUNDRY)&&mFoundry!=pRH.mFoundry) return false;
    if((mValid&VALID_ANTIALIAS)&&mAntialias!=pRH.mAntialias) return false;
    if((mValid&VALID_DPI)&&mDPI!=pRH.mDPI) return false;
    if((mValid&VALID_ANGLE)&&mAngle!=pRH.mAngle) return false;

    return true;
}

bool CFontInfo::operator!=(const CFontInfo &pRH) const
{
    return !(*this==pRH);
}

CFontInfo &CFontInfo::operator=(const CFontInfo &pRH)
{
    mValid=pRH.mValid;

    mFamily=pRH.mFamily;
    mStyle=pRH.mStyle;
    mSlant=pRH.mSlant;
    mWeight=pRH.mWeight;
    mSize=pRH.mSize;
    mWidth=pRH.mWidth;
    mAspect=pRH.mAspect;
    mPixelSize=pRH.mPixelSize;
    mSpacing=pRH.mSpacing;
    mFoundry=pRH.mFoundry;
    mAntialias=pRH.mAntialias;
    mDPI=pRH.mDPI;
    mAngle=pRH.mAngle;

    mHash=pRH.mHash;

    return (*this);
}

std::size_t CFontInfo::GetHash() const
{
    if(!(mValid&VALID_HASH)) CreateHash();

    return mHash;
}

void CFontInfo::CreateHash() const
{
    mValid|=VALID_HASH;

    mHash=0;

    using boost::hash_combine;

    if(mValid&VALID_FAMILY)
        hash_combine(mHash,mFamily);
    if(mValid&VALID_STYLE)
        hash_combine(mHash,mStyle);
    if(mValid&VALID_SLANT)
        hash_combine(mHash,(int)mSlant);
    if(mValid&VALID_WEIGHT)
        hash_combine(mHash,(int)mWeight);
    if(mValid&VALID_SIZE)
        hash_combine(mHash,mSize);
    if(mValid&VALID_WIDTH)
        hash_combine(mHash,mWidth);
    if(mValid&VALID_ASPECT)
        hash_combine(mHash,mAspect);
    if(mValid&VALID_PIXELSIZE)
        hash_combine(mHash,mPixelSize);
    if(mValid&VALID_SPACING)
        hash_combine(mHash,mSpacing);
    if(mValid&VALID_FOUNDRY)
        hash_combine(mHash,mFoundry);
    if(mValid&VALID_ANTIALIAS)
        hash_combine(mHash,mAntialias);
    if(mValid&VALID_DPI)
        hash_combine(mHash,mDPI);
    if(mValid&VALID_ANGLE)
        hash_combine(mHash,mAngle);
}

/*namespace img*/ } /*namespace buola*/ }
